#pragma once
#include "Vector3.h"


namespace Boon
{
	/*!
	* Represents an axis aligned bounding box (AABB) in 3D-space
	*/
	class BOON_API Bounds
	{
	public:

		Bounds( const Vector3& Center, const Vector3& Size )
			:	center( Center ), size( Size ), 
				boundMin( Vector3( center.x - size.x * .5f, center.y - size.y * .5f, center.z - size.z *.5f ) ),
				boundMax( Vector3( center.x + size.x * .5f, center.y + size.y * .5f, center.z + size.z *.5f ) )
		{

		}

		Bounds( const Bounds& b )
			:	center( b.center ),
				size( b.size ),
				boundMin( b.boundMin ),
				boundMax( b.boundMax)
		{

		}

		Bounds& operator=( const Bounds& rhs )
		{
			*const_cast<Vector3*>( &center ) = rhs.center;
			*const_cast<Vector3*>( &size ) = rhs.size;
			*const_cast<Vector3*>( &boundMin ) = rhs.boundMin;
			*const_cast<Vector3*>( &boundMax ) = rhs.boundMax;
			return *this;
		}

		/*! \brief		Sets new center of the bounding
		*/
		inline void					SetCenter( Vector3& Center )
		{
			*const_cast<Vector3*>( &center ) = Center;
		}

		/*! \brief		Sets new size and recalculates boundMin, boundMax
		*/
		inline void					SetSize( const Vector3& Size )
		{
			*const_cast<Vector3*>( &size ) = Size;
			*const_cast<Vector3*>( &boundMin ) = Vector3( center.x - Size.x * .5f, center.y - Size.y * .5f, center.z - Size.z *.5f );
			*const_cast<Vector3*>( &boundMax ) = Vector3( center.x + Size.x * .5f, center.y + Size.y * .5f, center.z + Size.z *.5f );
		}

		/*! \brief		AABB - Collision detections
			\param		b - Bounds to check against
			\return		bool - True on intersect
		*/
		inline bool					Intersects( const Bounds& b )
		{
			return	(	boundMin.x <= b.boundMax.x &&
						b.boundMin.x <= boundMax.x &&
						boundMin.y <= b.boundMax.y &&
						b.boundMin.y <= boundMax.y &&
						boundMin.z <= b.boundMax.z &&
						b.boundMin.z <= boundMax.z	);
		}

		void MirrorX()
		{
			const_cast<Vector3*>( &boundMin )->x = boundMin.x * -1.0f;
			const_cast<Vector3*>( &boundMax )->x = boundMax.x * -1.0f;
		}

		inline Vector3				GetFrontLeftBottom() const { return Vector3( boundMin.x, boundMin.y, boundMax.z ); }
		inline Vector3				GetFrontLeftTop() const	{ return Vector3( boundMin.x, boundMax.y, boundMax.z ); }
		inline Vector3				GetFrontRightTop() const { return Vector3( boundMax.x, boundMax.y, boundMax.z ); }
		inline Vector3				GetFrontRightBottom() const	{ return Vector3( boundMax.x, boundMin.y, boundMax.z ); }
		inline Vector3				GetBackLeftBottom() const {	return Vector3( boundMin.x, boundMin.y, boundMin.z ); }
		inline Vector3				GetBackLeftTop() const { return Vector3( boundMin.x, boundMax.y, boundMin.z ); }
		inline Vector3				GetBackRightTop() const { return Vector3( boundMax.x, boundMax.y, boundMin.z ); }
		inline Vector3				GetBackRightBottom() const { return Vector3( boundMax.x, boundMin.y, boundMin.z ); }

		inline Vector3				GetFrontLeftBottomLocal() const { return Vector3( boundMin.x, boundMin.y, boundMax.z ) - center; }
		inline Vector3				GetFrontLeftTopLocal() const	{ return Vector3( boundMin.x, boundMax.y, boundMax.z ) - center; }
		inline Vector3				GetFrontRightTopLocal() const { return Vector3( boundMax.x, boundMax.y, boundMax.z ) - center; }
		inline Vector3				GetFrontRightBottomLocal() const	{ return Vector3( boundMax.x, boundMin.y, boundMax.z ) - center; }
		inline Vector3				GetBackLeftBottomLocal() const {	return Vector3( boundMin.x, boundMin.y, boundMin.z ) - center; }
		inline Vector3				GetBackLeftTopLocal() const { return Vector3( boundMin.x, boundMax.y, boundMin.z ) - center; }
		inline Vector3				GetBackRightTopLocal() const { return Vector3( boundMax.x, boundMax.y, boundMin.z ) - center; }
		inline Vector3				GetBackRightBottomLocal() const { return Vector3( boundMax.x, boundMin.y, boundMin.z ) - center; }

		const Vector3				center;
		const Vector3				size;
		const Vector3				boundMin, boundMax;
	};


}
